if Installed('leaderf')
    nnoremap <silent><M-l><M-l> :Leaderf line --no-sort<Cr>
    nnoremap <silent><M-l>l :Leaderf line --all --no-sort<Cr>
else
    nnoremap <silent><M-l><M-l> :FzfBLines<Cr>
    nnoremap <silent><M-l>l :FzfLines<Cr>
endif
" --------------------------
" search in current buffer
" --------------------------
function s:vimgrep(...)
    try
        if a:0 == 0
            let cword = expand('<cword>')
        else
            let cword = a:1
        endif
    catch /.*/
        let cword = ""
    endtry
    if empty(cword)
        call preview#errmsg("No search word offered")
    else
        execute('vimgrep /' . cword . '/ %')
        belowright copen
    endif
endfunction
command! -nargs=? SearchCurr call s:vimgrep(<f-args>)
nnoremap \| :SearchCurr <C-r>=expand('<cword>')<Cr><Cr>
xnoremap \| :<C-u>SearchCurr <C-r>=GetVisualSelection()<Cr><Cr>
nnoremap s\ :SearchCurr <C-r>=expand('<cword>')<Cr>
xnoremap s\ :<C-u>SearchCurr <C-r>=GetVisualSelection()<Cr>
" --------------------------
" searh tools
" --------------------------
let g:grepper = {
            \ 'open': 1,
            \ 'quickfix': 1,
            \ 'searchreg': 1,
            \ 'highlight': 0,
            \ }
PlugAddOpt 'vim-grepper'
" autocmd User Grepper copen function
function! s:grepper(...)
    " a:0 is the argments number of the parameters
    if a:0 != 2
        call preview#errmsg('Parameters for s:grepper is wrong')
        return
    endif
    if (a:1 == 2 || a:1 == 0 && a:2 == 1) && !empty(GitRootPath())
        let cd_root = 1
        let search_cmd = 'GrepperGit'
    else
        let cd_root = 0
        let search_cmd = 'GrepperRg'
    endif
    " a:1 is the 1st of parameters
    if a:1
        let search_str = substitute(a:2, '[\/]\+$', '', '')
        if a:1 == 1
            let g:grepper_last_search = search_str
        else
            let g:grepper_all_last_search = search_str
        endif
    else
        if a:2 == 0
            let search_str = get(g:, 'grepper_last_search', '')
        else
            let search_str = get(g:, 'grepper_all_last_search', '')
        endif
    endif
    if search_str == ''
        if a:1 == 1
            echo "Grepper search last str is empty"
        else
            echo "Grepper search all last str is empty"
        endif
    else
        if cd_root
            cd %:h | cd `git rev-parse --show-toplevel`
        else
            lcd %:p:h
        endif
        execute search_cmd . ' ' . search_str
    endif
endfunction
" Commands
command! -nargs=1 GrepperSearch    call s:grepper(1, <f-args>)
command! -nargs=1 GrepperSearchAll call s:grepper(2, <f-args>)
command! GrepperSearchLast    call s:grepper(0, 0)
command! GrepperSearchAllLast call s:grepper(0, 1)
" map
nnoremap s: :Grepper
" GrepperSearchAll
nnoremap s<Cr> :GrepperSearchAll <C-r>=expand('<cword>')<Cr>
xnoremap s<Cr> :<C-u>GrepperSearchAll <C-r>=GetVisualSelection()<Cr>
nnoremap s. :GrepperSearchAllLast<Cr>
nnoremap s' :GrepperSearchAll ""<Left>
xnoremap s' :<C-u>GrepperSearchAll "<C-r>=GetVisualSelection()<Cr>"
" GrepperSearch
nnoremap s] :GrepperSearch <C-r>=expand('<cword>')<Cr>
xnoremap s] :<C-u>GrepperSearch <C-r>=GetVisualSelection()<Cr>
nnoremap s[ :GrepperSearchLast<Cr>
nnoremap s" :GrepperSearch ""<Left>
xnoremap s" :<C-u>GrepperSearch "<C-r>=GetVisualSelection()<Cr>"
" r as cdo replace
au FileType qf nnoremap <buffer>r :cdo s///gc<Left><Left><Left>
au FileType qf nnoremap <buffer><M-r> :cdo s///gc<Left><Left><Left>
au FileType qf nnoremap <buffer><M-S> :cfdo up
cnoremap <M-S> cfdo up
" --------------------------
" searchall
" --------------------------
if Installed('leaderf') && executable('rg')
    if InstalledFzf()
        let g:search_tool = "grepper-fzf-leaderf"
    else
        let g:search_tool = "grepper-leaderf"
    endif
    let g:Lf_RgConfig = [
                \ "--max-columns=10000",
                \ "--glob=!{.git,.svn,.hg,.project}",
                \ "--hidden"
                \ ]
    let g:Lf_RgStorePattern = "e"
    " map
    nnoremap <C-f>: :Leaderf rg<Space>
    " flygrep fuzzy mode
    nnoremap <silent>,/ :Leaderf rg --auto-preview --fuzzy -L -S --wd-mode=f<Cr>
    nnoremap <silent>,? :Leaderf rg --auto-preview --fuzzy -L -S<Cr>
    nnoremap <silent>,\ :Leaderf rg --auto-preview --fuzzy -L -S --wd-mode=f --cword<Cr>
    nnoremap <silent>,\| :Leaderf rg --auto-preview --fuzzy -L -S --cword<Cr>
    " recall previous next recall
    nnoremap <silent><C-f>; :Leaderf rg --next<Cr>
    nnoremap <silent><C-f>, :Leaderf rg --previous<Cr>
    nnoremap <silent><C-f>. :Leaderf rg --recal<Cr>
    " C-f map in bottom
    nnoremap <silent><C-f>e :Leaderf! rg --bottom -L -S -e "<C-r>=expand('<cword>')<Cr>"
    xnoremap <silent><C-f>e :<C-u>Leaderf! rg --bottom -L -S -e "<C-r>=GetVisualSelection()<Cr>"
    nnoremap <silent><C-f>b :Leaderf! rg --bottom -L -S --all-buffers "<C-r>=expand('<cword>')<Cr>"
    xnoremap <silent><C-f>b :<C-u>Leaderf! rg --bottom -L -S --all-buffers "<C-r>=GetVisualSelection()<Cr>"
    nnoremap <silent><C-f>w :Leaderf! rg --bottom -L -S -w "<C-r>=expand('<cword>')<Cr>"
    xnoremap <silent><C-f>w :<C-u>Leaderf! rg --bottom -L -S -w "<C-r>=GetVisualSelection()<Cr>"
    nnoremap <silent><C-f>f :Leaderf! rg --bottom -L -S -F "<C-r>=expand('<cword>')<Cr>"
    xnoremap <silent><C-f>f :<C-u>Leaderf! rg --bottom -L -S -F "<C-r>=GetVisualSelection()<Cr>"
    nnoremap <silent><C-f>x :Leaderf! rg --bottom -L -S -x "<C-r>=expand('<cword>')<Cr>"
    xnoremap <silent><C-f>x :<C-u>Leaderf! rg --bottom -L -S -x "<C-r>=GetVisualSelection()<Cr>"
    nnoremap <silent><C-f>a :Leaderf! rg --bottom --append "<C-r>=expand('<cword>')<Cr>"
    xnoremap <silent><C-f>a :<C-u>Leaderf! rg --bottom --append "<C-r>=GetVisualSelection()<Cr>"
    nnoremap <silent><C-f>i :LeaderfRgInteractive<Cr>
    " leaderf_search
    function! s:leaderf_search(all, ...) abort
        let cmd = 'Leaderf! rg --bottom -L -S '
        if a:0 > 0
            let cmd = cmd . a:1
        endif
        if a:all == 0
            let cmd = cmd . ' --wd-mode=F'
        endif
        exec cmd
    endfunction
    command! -nargs=* LeaderfSearchAll call s:leaderf_search(1, <f-args>)
    command! -nargs=* LeaderfSearch    call s:leaderf_search(0, <f-args>)
    nnoremap <C-f><Cr> :LeaderfSearchAll <C-r>=expand('<cword>')<Cr>
    xnoremap <C-f><Cr> :<C-u>LeaderfSearchAll <C-r>=GetVisualSelection()<Cr>
    nnoremap <C-f>] :LeaderfSearch <C-r>=expand('<cword>')<Cr>
    xnoremap <C-f>] :<C-u>LeaderfSearch <C-r>=GetVisualSelection()<Cr>
    nnoremap <C-f>/ :LeaderfSearchAll<Space>
    nnoremap <C-f>? :LeaderfSearch<Space>
elseif InstalledFzf()
    let g:search_tool = 'grepper-fzfsearch'
    function! s:fzf_search(...)
        if a:1 == 2 && !empty(GitRootPath())
            let fzf_cmd = 'FzfGGrep'
        else
            let fzf_cmd = 'FzfRG'
        endif
        " a:0 代表参数数量, a1 代表 第一个参数
        lcd %:p:h
        if a:1 == 0
            " FzfFlyGrep
            execute fzf_cmd
        else
            " fzfsearch, a:1 == 1
            if a:1 == 1
                if a:0 == 1
                    let search_str = get(g:, 'fzf_search_last', '')
                else
                    let search_str = substitute(a:2, '[\/]\+$', '', '')
                    let g:fzf_search_last = search_str
                endif
                " fzfsearchall, a:1 == 2
            else
                if a:0 == 1
                    let search_str = get(g:, 'fzf_searchall_last', '')
                else
                    let search_str = substitute(a:2, '[\/]\+$', '', '')
                    let g:fzf_searchall_last = search_str
                endif
            endif
            " do the search
            if search_str == ''
                if a:0 == 1
                    echo 'fzf search last is empty'
                else
                    echo 'fzf search str is empty'
                endif
                return
            else
                execute fzf_cmd . ' ' . search_str
            endif
        endif
    endfunction
    command! FzfFlyGrep call s:fzf_search(0)
    command! FzfSearchLast call s:fzf_search(1)
    command! -nargs=1 FzfSearch call s:fzf_search(1, <f-args>)
    command! FzfSearchAllLast call s:fzf_search(2)
    command! -nargs=1 FzfSearchAll call s:fzf_search(2, <f-args>)
    " searchall
    nnoremap <C-f><Cr> :FzfSearchAll <C-r>=expand('<cword>')<Cr>
    xnoremap <C-f><Cr> :<C-u>FzfSearchAll <C-r>=GetVisualSelection()<Cr>
    nnoremap <C-f>. :FzfSearchAllLast<Cr>
    nnoremap <C-f>/ :FzfSearchAll<Space>
    " search
    nnoremap <C-f>] :FzfSearch <C-r>=expand('<cword>')<Cr>
    xnoremap <C-f>] :<C-u>FzfSearch <C-r>=GetVisualSelection()<Cr>
    nnoremap <C-f>[ :FzfSearchLast<Cr>
    nnoremap <C-f>? :FzfSearch<Space>
else
    let g:search_tool = 'grepper'
endif
if InstalledFzf()
    nnoremap <silent><leader>/ :FzfRg<Cr>
    nnoremap <silent><leader>? :FzfGGrep<Cr>
    nnoremap <silent><leader>\ :FzfRg <C-r>=expand('<cword>')<Cr><Cr>
    nnoremap <silent><leader>\| :FzfGGrep <C-r>=expand('<cword>')<Cr><Cr>
    if Installed('leaderf')
        nnoremap <silent><Tab>/ :Leaderf rg --auto-preview -L -S --wd-mode=f<Cr>
        nnoremap <silent><Tab>? :Leaderf rg --auto-preview -L -S<Cr>
        nnoremap <silent><Tab>\ :Leaderf rg --auto-preview -L -S --wd-mode=f --cword<Cr>
        nnoremap <silent><Tab>\| :Leaderf rg --auto-preview -L -S --cword<Cr>
    endif
elseif Installed('leaderf')
    nnoremap <silent><leader>/ :Leaderf rg --auto-preview -L -S --wd-mode=f<Cr>
    nnoremap <silent><leader>? :Leaderf rg --auto-preview -L -S<Cr>
    nnoremap <silent><leader>\ :Leaderf rg --auto-preview -L -S --wd-mode=f --cword<Cr>
    nnoremap <silent><leader>\| :Leaderf rg --auto-preview -L -S --wd-mode=f<Cr>
endif
" TODO NOTE search
if Installed('leaderf')
    command! TODO call s:leaderf_search(1, g:todo_patterns)
    command! NOTE call s:leaderf_search(1, g:note_patterns)
else
    function! s:grepper_patterns_search(patterns)
        if get(b:, 'git_root_path', '') != ''
            execute printf('GrepperGit -E "%s:"', a:patterns)
        else
            execute printf('GrepperRg -e "%s:"', a:patterns)
        endif
    endfunction
    command! TODO call s:grepper_patterns_search(g:todo_patterns)
    command! NOTE call s:grepper_patterns_search(g:note_patterns)
endif
nnoremap <silent><C-f>t :TODO<Cr>
nnoremap <silent><C-f>n :NOTE<Cr>
" ----------------------------
" bqf && quickui
" ----------------------------
if Installed('nvim-bqf')
    luafile $LUA_PATH/bqf.lua
    hi default link BqfPreviewFloat Normal
    hi default link BqfPreviewBorder Normal
    hi default link BqfPreviewCursor Cursor
    hi default link BqfPreviewRange IncSearch
    hi link BqfPreviewRange Search
    hi default BqfSign ctermfg=14 guifg=Cyan
    hi BqfPreviewBorder guifg=#50a14f ctermfg=71
    aug Grepper
        au!
        au User Grepper call setqflist([], 'r',
                    \ {'context': {'bqf': {'pattern_hl': histget('/')}}}) |
                    \ botright copen
    aug END
endif
" ----------------------------------
" ufo
" ----------------------------------
if Installed('nvim-ufo', 'promise-async')
    lua require('ufo').setup()
else
    PlugAddOpt 'vim-searchindex'
endif
" ----------------------------------
" hl searchindex && multi replace
" ----------------------------------
if Installed('nvim-hlslens')
    lua require('hlslens').setup()
    nnoremap <silent>n <Cmd>execute('normal! ' . v:count1 . 'n')<Cr><Cmd>lua require('hlslens').start()<Cr>
    nnoremap <silent>N <Cmd>execute('normal! ' . v:count1 . 'N')<Cr><Cmd>lua require('hlslens').start()<Cr>
    nnoremap <silent>*  *``<Cmd>lua require('hlslens').start()<Cr>
    nnoremap <silent>#  #``<Cmd>lua require('hlslens').start()<Cr>
    nnoremap <silent>g* g*``<Cmd>lua require('hlslens').start()<Cr>
    nnoremap <silent>g# g#``<Cmd>lua require('hlslens').start()<Cr>
    nnoremap <C-n> *``<Cmd>lua require('hlslens').start()<Cr>cgn
else
    nnoremap <silent>*  *``
    nnoremap <silent>#  #``
    nnoremap <silent>g* g*``
    nnoremap <silent>g# g#``
    nnoremap <C-n> *``cgn
endif
function! EnhancedSearch() range
    let l:saved_reg = @"
    execute 'normal! vgvy'
    let l:pattern = escape(@", "\\/.*'$^~[]")
    let l:pattern = substitute(l:pattern, "\n$", "", "")
    let @/ = l:pattern
    let @" = l:saved_reg
endfunction
xmap <silent><C-n> :<C-u>call EnhancedSearch()<Cr>/<C-R>=@/<Cr><Cr>gvc
